package com.nulldev.util.date;

import java.util.Date;

import com.nulldev.util.java.JVMUtil;
import com.nulldev.util.java.date.DateUtil;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.math.lNumber;

public class ExtendedTime {
	
	public static void main(String[] args) {
		//JVMUtil.async_println("Current Time: " + get());
		//JVMUtil.async_println("Current Time.debug: " + get().toRString());
	}
	
	private final static Logger log = LoggerFactory.getLogger(true, true);
	
	/*
	 * Extended Time API (Beating the limit of 2038 on UNIX)
	 * 
	 * 
	 * 
	 */

	public static long u64_time = System.currentTimeMillis();
	private static lNumber uext_time = lNumber.nil();
	private static boolean running;
	static {
		if (!running) {
			// attempt to sync with Java API + System Time
			try {
				final Date inital = DateUtil.get();
				final String stime = String.valueOf(inital.getTime());
				if (!stime.endsWith("000")) {
					log.debug("Syncing time...");
					while (String.valueOf(DateUtil.get().getTime()).endsWith("000"));
				}
				uext_time = uext_time.set(inital.getTime());
				if (lNumber.fromInt(Integer.MAX_VALUE).minus(uext_time).lessThanZero()) {
					log.debug("Could not use time as a 32bit Integer, using 64bit long!");
				}
			}catch (Exception e) {
				log.error("Could not get system time!", e);
				uext_time.setSelf(Integer.MAX_VALUE);
			}
			try {
				log.info("ExtendedTime API is ready. You should use this API in " + (lNumber.fromLong(Long.MAX_VALUE).minus(uext_time)) + " ms.");
			}catch (Exception e) {}
			final Runnable r = new Runnable() {
				
				@Override
				public void run() {
					while (true) {;
						uext_time.addSelf(1000L); // = uext_time.add(1000L);
						//System.out.println(uext_time.toString());
						try {
							Thread.sleep(1000L);
						} catch (InterruptedException e) {
						}
					}
				}
			};
			final Thread tr = new Thread(r, "nullUtil.Time.ExtendedManager | nullUtil 2.4.1+: ExtendedTime Manager");
			tr.start();
			running = true;
		}
	}
	
	public static lNumber get() {
		return uext_time;
	}
	
	public static lNumber daysSince1970() {
		final lNumber lx = uext_time.clone();
		return lx.divide((1000*60*60*24));
	}
	
	public static lNumber hoursSince1970() {
		final lNumber lx = uext_time.clone();
		return lx.divide((1000*60*60));
	}
	
	public static lNumber minsSince1970() {
		final lNumber lx = uext_time.clone();
		return lx.divide((1000*60));
	}
	
	public static lNumber secondsSince1970() {
		final lNumber lx = uext_time.clone();
		return lx.divide((1000));
	}
}
